<?php

namespace App\Models;

use App\Http\Helper\ServerAPI;
use App\Http\Helper\UrlSchemaHelper;
use App\Models\Concerns\CommentTraits;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use DB;
use Tymon\JWTAuth\Facades\JWTAuth;

/**
 * Class User
 * @property integer id
 * @property string name
 * @property string email
 * @property string password
 * @property string avatar 用户头像
 * @property integer wx_user_id 微信用户表ID
 * @property string phone 电话号
 * @property string wx_id 微信号
 * @property integer age 年龄
 * @property string school 学校
 * @property string major 专业
 * @property string interest 兴趣
 * @property string city 城市
 * @property string intro 个人介绍
 * @property string constellation 星座
 * @property integer identity 身份
 * @property integer locking 是否锁定  0：否  1：是
 * @property integer accept_count 接单次数
 * @property double earnings 收益
 * @property double lock_earnings 提现时锁定收益
 * @property double star 星级
 * @property WxUser wx_user 绑定的微信账号
 * @property integer audit 是否通过身份认证 0:未提交  1：审核中  2：审核成功  3：审核失败
 * @property integer invitation_code_id 邀请码id
 * @property boolean audit_95 是否通过95后认证
 * @property date birthday 生日
 */
class User extends ApplicationModel implements AuthenticatableContract,
    AuthorizableContract,
    CanResetPasswordContract
{
    use Authenticatable, Authorizable, CanResetPassword;
    use CommentTraits;

    const IDENTITY_BUYERS = 1;//买家
    const IDENTITY_SELLER = 2;//卖家

    const AUDITING = 1;//审核中
    const AUDIT_SUCCESS = 2;//审核通过
    const AUDIT_FAIL = 3;//审核失败
    const AUDIT_PHOTO_FAIL = 4;//审核失败

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'id',
        'name',
        'email',
        'password',
        'avatar',
        'phone',
        'wx_user_id',
        'wx_id',
        'age',
        'school',
        'sex',
        'city',
        'major',
        'interest',
        'identity',
        'earnings',
        'source',
        'channel',
        'locking',
        'yun_xin_password',
        'intro',
        'latitude',
        'longitude',
        'birthday',
        'audit',
        'audit_95',
        'star',
        'lock_earnings',
        'constellation',
        'accept_count',
        'invitation_code_id',
    ];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = ['remember_token'];

    /**
     * Get logged user info.
     *
     * @return mixed
     */
    public static function getAuthenticatedUser()
    {
        try {
            $user = JWTAuth::parseToken('token', 'token')->authenticate();
        } catch (TokenExpiredException $e) {
            return response()->json(['error' => 'token_expired'], $e->getStatusCode());
        } catch (TokenInvalidException $e) {
            return response()->json(['error' => 'token_invalid'], $e->getStatusCode());
        } catch (JWTException $e) {
            return response()->json(['error' => 'token_absent'], $e->getStatusCode());
        }
        // the token is valid and we have found the user via the sub claim
        return $user;
    }

    public function avatar()
    {
        return starts_with($this->avatar, 'http://') ? $this->avatar : $this->img_host() . $this->avatar;
    }

    public function phone()
    {
        $c = UserChildAccount::where('user_id', $this->id)->first();
        if ($c) {
            $parent = User::find($c->parent_id);
            if ($parent) {
                return $parent->phone;
            }
        }
        if (!isMobile($this->phone)) {
            return false;
        }
        return $this->phone;
    }

    public function new_phone(){
        $au = Auth::guard('admin')->user();
        if($au->id == 1){
            return $this->phone;
        }
        return substr_replace($this->phone,'****',3,4);
    }

    /**
     * 验证用户的验证码
     * @param $phone 手机号
     * @param $code 验证码
     * @return bool
     */
    public static function verify_code($phone, $code)
    {
        $key = self::phone_code_key($phone);
        \Log::info(Cache::get($key), ['cache code']);
        if (strlen($code) && Cache::get($key) == $code) {
//            Cache::forget($key);
            return true;
        }
        return false;
    }

    /**
     * 生成验证码并存到cache中
     * @param $phone
     * @param $code
     */
    public static function set_cache_code($phone, $code)
    {
        $key = self::phone_code_key($phone);
        Cache::put($key, $code, 5);
    }

    /**
     * 保存流水
     * @param $total 总金额
     * @param $from_user_id 来自哪个用户
     * @param $purchase_id 订单id
     * @param $product_id 商品id
     * @param $source 来源
     * @param int $type 类型（收入或支出）
     * @param string $detail 描述
     * @return bool
     */
    public function add_earnings($total, $from_user_id, $purchase_id, $product_id, $source, $type = EarningsLog::TYPE_IN, $detail = '', $service_charge = 0)
    {
        if (EarningsLog::valid_double($purchase_id, $this->id, $from_user_id, $type, $source)) {
            return false;
        }
        if ($type == 1) {
            $this->earnings += $total;
            $this->save();
        }

        $earnings = new EarningsLog();
        $earnings->from_user_id = $from_user_id;
        $earnings->price = $total;
        $earnings->purchase_id = $purchase_id;
        $earnings->product_id = $product_id;
        $earnings->detail = $detail;
        $earnings->user_id = $this->id;
        $earnings->type = $type;
        $earnings->source = $source;
        $earnings->service_charge = $service_charge;

        $earnings->save();

    }

    /**
     * 生成验证码存到cache中的key
     * @param $phone
     * @return string
     */
    public static function phone_code_key($phone)
    {
        $key = "signup:" . $phone;
        return $key;
    }

    public function seller_purchases()
    {
        return $this->hasMany(Purchase::class, 'seller_user_id', 'id')->where('is_payed', true);
    }


    public function purchases()
    {
        return $this->hasMany(Purchase::class);
    }

    public function products()
    {
        return $this->hasMany(Product::class)->orderBy('created_at', 'desc')->where('is_report', false);
    }

    public function is_comment($purchase_id)
    {
        return Comment::where('user_id', $this->id)->where('other_id', $purchase_id)->count() > 0;
    }

    public function wx_user()
    {
        return $this->hasOne(WxUser::class);
    }

    public function has_skill($skill_id)
    {
        $res = $this->products()->where('skill_id', $skill_id)->orderBy('created_at', 'desc')->first();
        if ($res && $res->status != Product::STATUS_REJECT) {
            return $res->status;
        }

        return 0;
    }

    public function userIdentity()
    {
        return $this->hasMany(UserIdentity::class)->orderBy('created_at', 'desc');
    }

    public function userInterests()
    {
        return $this->hasMany(UserInterest::class);
    }

    public function messages($type = 'system')
    {
        return $this->hasMany(Message::class)->where('type', $type);
    }

    /**
     * 我关注的用户
     * @return mixed
     */
    public function myFollowUsers()
    {
        return $this->hasMany(Follow::class)->where('type', $this->model_name());
    }

    /**
     * 关注我的用户
     * @return mixed
     */
    public function followUsers()
    {
        return $this->hasMany(Follow::class, 'type_id')->where('type', $this->model_name());
    }

    public function devices()
    {
        return $this->hasMany(UserDevice::class);
    }

    public function useDevice()
    {
        return $this->devices()->orderBy('updated_at', 'desc')->first();
    }

    public function invitationCode()
    {
        return $this->belongsTo(InvitationCode::class);
    }

    public function couponNumbers()
    {
        return $this->hasMany(CouponNumber::class);
    }


    public function share_content()
    {
        $do_main = config('constants.DO_MAIN');
        $arr = array(
            'qqShare' => array('title' => '此人身怀绝技，在CC星球等你', 'content' => '快来CC星球围观“' . $this->name . '”', 'url' => $do_main . '/app/download.html', 'cover' => ($this->avatar ? $this->avatar : 'https://img.superxing.cc/api/img/official_logo.png')),
            'wxShare' => array('title' => '此人身怀绝技，在CC星球等你', 'content' => '快来CC星球围观“' . $this->name . '”', 'url' => $do_main . '/app/download.html', 'cover' => ($this->avatar ? $this->avatar : 'https://img.superxing.cc/api/img/official_logo.png')),
            'wxQuan' => array('title' => '此人身怀绝技，在CC星球等你', 'content' => '此人身怀绝技，在CC星球等你', 'url' => $do_main . '/app/download.html', 'cover' => ($this->avatar ? $this->avatar : 'https://img.superxing.cc/api/img/official_logo.png')),
            'wbShare' => array('title' => '此人身怀绝技，在CC星球等你', 'content' => '快来CC星球围观“' . $this->name . '”', 'url' => $do_main . '/app/download.html', 'cover' => ($this->avatar ? $this->avatar : 'https://img.superxing.cc/api/img/official_logo.png')),
            'qqZone' => array('title' => '此人身怀绝技，在CC星球等你', 'content' => '快来CC星球围观“' . $this->name . '”', 'url' => $do_main . '/app/download.html', 'cover' => ($this->avatar ? $this->avatar : 'https://img.superxing.cc/api/img/official_logo.png')),
        );

        return $arr;
    }

    public static function getAge($birthday)
    {
        $age = strtotime($birthday);
        if ($age === false) {
            return false;
        }
        list($y1, $m1, $d1) = explode("-", date("Y-m-d", $age));
        $now = strtotime("now");
        list($y2, $m2, $d2) = explode("-", date("Y-m-d", $now));
        $age = $y2 - $y1;
        if ((int)($m2 . $d2) < (int)($m1 . $d1))
            $age -= 1;
        return $age;
    }

    public function accept_count()
    {
//        return $this->seller_purchases()->whereIn('source', [Purchase::SOURCE_APP, 'import'])->whereIn('status', array(Purchase::STATUS_SELLER_ACCEPT, Purchase::STATUS_FINISH))->count();
        return $this->accept_count;
    }

    /**
     * 更新云信的名片
     * @param $user
     * @return bool
     */
    public function updateYunXinInfo()
    {
        //刷新云信token
        $avatar = $this->avatar;
        if (!$this->avatar) {
            $avatar = 'https://img.superxing.cc/api/img/default_avatar.png';
        }
        $yunXinSer = new ServerAPI();
        $yunXinSer->updateUinfo($this->id, $this->name, $avatar);
    }

    public function sex_str()
    {
        switch ($this->sex) {
            case 1:
                return '男';
                break;
            case 2:
                return '女';
                break;
            default:
                return '未知';
        }
    }

    public function earnings()
    {
        return round($this->earnings - $this->lock_earnings, 2);
    }

    /**
     * 获取用户的兴趣关联的技能id
     * @return array
     */
    public function get_interest_skill_ids()
    {
        $user_interests = $this->userInterests;
        $skill_ids = array();
        foreach ($user_interests as $user_interest) {
            $interest = $user_interest->interest;
            if ($interest) {
                $tmp_ids = json_decode($interest->skill_ids) ?: array();
                foreach ($tmp_ids as $tmp_id) {
                    $skill = Skill::release()->where('id', $tmp_id)->first();
                    if (!in_array($tmp_id, $skill_ids) && $skill) {
                        $skill_ids[] = $tmp_id;
                    }
                }
            }
        }
        return $skill_ids;
    }

    public function withdraws()
    {
        return $this->hasMany(EarningsLog::class)->where('detail', '提现')->where('type', EarningsLog::TYPE_OUT);
    }

    public function audit_fail_reason()
    {
        if ($this->audit == 3) {
            return '您的身份证信息有误';
        }
        if ($this->audit == 3) {
            return '您的照片不符合要求';
        }
        return '';
    }

    public function is_subscribe_wx()
    {
        $wx_user = $this->wx_user;
        if (!empty($wx_user->open_id) && starts_with($wx_user->open_id, 'o88')) {
            return true;
        }
        return false;
    }

    public function vip_day_count()
    {
        $vip_user = $this->hasMany(VipUser::class)->where('end_date', '>', date('Y-m-d'))->orderBy('end_date', 'desc')->first();
        if (!$vip_user) {
            return 0;
        }
        $datetime1 = date_create(date('Y-m-d'));
        $datetime2 = date_create($vip_user->end_date);
        $interval = date_diff($datetime1, $datetime2);
        $count = $interval->format('%a');

        return $count;
    }

    /**
     * 用户的平台服务费
     */
    public function service_charge()
    {
        $service_charge = $this->hasMany(UserServiceCharge::class)->where('start_date', '>=', date('Y-m-d'))->where('end_date', '<=', date('Y-m-d'))->first();
        if ($service_charge) {
            return $service_charge->scale / 100;
        }
        return 0.1;
    }

    /**
     *  计算.星座
     *
     * @param int $month 月份
     * @param int $day 日期
     * @return str
     */
    public function get_constellation()
    {
        $month = date('m', strtotime($this->birthday));
        $day = date('d', strtotime($this->birthday));
        $signs = array(
            array('20' => '水瓶座'), array('19' => '双鱼座'),
            array('21' => '白羊座'), array('20' => '金牛座'),
            array('21' => '双子座'), array('22' => '巨蟹座'),
            array('23' => '狮子座'), array('23' => '处女座'),
            array('23' => '天秤座'), array('24' => '天蝎座'),
            array('22' => '射手座'), array('22' => '摩羯座')
        );
        $key = (int)$month - 1;
        list($startSign, $signName) = each($signs[$key]);
        if ($day < $startSign) {
            $key = $month - 2 < 0 ? $month = 11 : $month -= 2;
            list($startSign, $signName) = each($signs[$key]);
        }
        return $signName;
    }

    /**
     * 给关注用户发送推送
     * @param $type 类型 动态：dynamic 服务：product
     * @param $type_id 类型对应的id
     */
    public function push_follow($type, $type_id, $content)
    {
        $follows = $this->followUsers;
        $ios = array();
        $android = array();
        $i = 0;
        $j = 0;
        $url = UrlSchemaHelper::get_url_schema($type) . $type_id;
        foreach ($follows as $follow) {
            if (!empty($follow->user->id) && !empty($follow->user->useDevice()->device_type)) {
                if ($follow->is_push && $follow->user->useDevice()->device_type == 'ios') {
                    $ios[$i][] = $follow->user->useDevice()->device_id;
                    if (count($ios[$i]) == 100) {
                        $i++;
                    }
                }
                if ($follow->is_push && $follow->user->useDevice()->device_type == 'android') {
                    $android[$j][] = $follow->user->useDevice()->device_id;
                    if (count($android[$j]) == 100) {
                        $j++;
                    }
                }
                date_default_timezone_set('Asia/shanghai');
                $message = new Message();
                $message->user_id = $follow->user->id;
                $message->content = $content;
                $message->icon = Message::ICON;
                $message->url_schema = $url;
                $message->type_id = $type_id;
                $message->save();
            }
        }
        $msg = new Message();
        if (count($ios) > 0) {
            $msg->pushMoreMsg($ios, 'ios', $content, "{'url':'$url'}");
        }
        if (count($android) > 0) {
            $msg->pushMoreMsg($android, 'android', $content, "{'url':'$url'}");
        }
    }
}
